package com.soul.dubbo.api.mongo;

import com.soul.dubbo.async.TimeLineService;
import com.soul.dubbo.utils.IdWorker;
import com.soul.model.mongo.Friend;
import com.soul.model.mongo.Movement;
import com.soul.model.mongo.MovementTimeLine;
import com.soul.model.vo.MovementsVo;
import com.soul.model.vo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author mdoya
 * @version 1.0
 * @description:
 */
@Slf4j
@DubboService
public class MovementApiImpl implements MovementApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private TimeLineService timeLineService;

    @Override
    public String addMovements(Movement movement) {
        // 用户id
        Long currendUserId = movement.getUserId();
        // 保存用户动态
        Long nowTime = System.currentTimeMillis();
//        movement.setId(ObjectId.get());
        movement.setCreated(nowTime);
        // 推荐系统要使用字段 自增长列 从1开始
        movement.setPid(idWorker.getNextId("movement"));
        Movement m = mongoTemplate.insert(movement);

        // 查询可见用户
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(currendUserId));
        List<Friend> friends = mongoTemplate.find(query, Friend.class);
        System.err.println("朋友数量：： " +friends.size());
        // 保存时间线集合
        log.debug("开始发布个人动态");
        timeLineService.addTimeLine(movement,currendUserId,nowTime,friends);
        log.debug("成功发布个人动态");
        /*if (!CollectionUtils.isEmpty(friends)){
            for (Friend friend : friends) {
                MovementTimeLine movementTimeLine = new MovementTimeLine();
                movementTimeLine.setUserId(userId);
                movementTimeLine.setFriendId(friend.getFriendId());
                movementTimeLine.setMovementId(movement.getId());
                movementTimeLine.setCreated(nowTime);
                mongoTemplate.insert(movementTimeLine);
            }
        }*/
        System.err.println("用户圈子发布成功！！");
        return m.getId().toHexString();
    }

    @Override
    public PageResult<Movement> findPageMovement(Long page, Long pageSize, Long userId) {
        // 1、 查询总记录数
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        long counts = mongoTemplate.count(query, Movement.class);
        // 2、 当前页面数据
        query.limit(pageSize.intValue()).skip((page-1)*pageSize);
        // 2.1 date降序
        query.with(Sort.by(Sort.Direction.DESC,"created"));
        List<Movement> movementList = mongoTemplate.find(query, Movement.class);
        // 3、 返回PageResult
        return new PageResult<>(page,pageSize,counts,movementList);
    }

    /**
     * 圈子 - 好友动态
     * @param page     每个码数
     * @param pagesize 每页条数
     * @param userId   登录用户id
     * @return PageResult
     */
    @Override
    public PageResult<Movement> findFriendPageMovements(Long page, Long pagesize, Long userId) {
        // 1. 查询好友动态总数量
        Query query = new Query();
        query.addCriteria(Criteria.where("friendId").is(userId));
        long count = mongoTemplate.count(query, MovementTimeLine.class);

        // 2. 查询好友动态并且分页 手动分页
        query.with(Sort.by(Sort.Direction.DESC,"created"));
        query.skip((page - 1) * pagesize).limit(pagesize.intValue());
        List<MovementTimeLine> movementTimeLineList = mongoTemplate.find(query, MovementTimeLine.class);

        // 3. 根据时间表找到动态id
        List<Movement> movements = null;
        if (!CollectionUtils.isEmpty(movementTimeLineList)){
            List<ObjectId> movementIdsList = movementTimeLineList.stream().map(MovementTimeLine::getMovementId).collect(Collectors.toList());

            Query query2 = new Query();
            query2.addCriteria(Criteria.where("id").in(movementIdsList));
            movements = mongoTemplate.find(query2, Movement.class);
        }
        return new PageResult<Movement>(page,pagesize,count,movements);
    }

    /**
     * 圈子 - 推荐动态
     *
     * @param page     每个码数
     * @param pagesize 每页条数
     * @param userId   登录用户id
     * @return PageResult
     */
    @Override
    public List<Movement> randomMovement(Long page, Long pagesize, Long userId) {
        // 1. 推荐动态总条数
        Query query = new Query();
        long count = mongoTemplate.count(query, Movement.class);
        // 2. 总条数少于10则返回所有条数
        if (count < 10) {
           return mongoTemplate.find(query,Movement.class);
        }
        // 3. 总条数大于10则随机选择10条推荐动态
        long startIndex = RandomUtils.nextLong(0, count - 9);
        query.skip(startIndex).limit(pagesize.intValue());
        query.with(Sort.by(Sort.Direction.ASC,"created"));
        return mongoTemplate.find(query, Movement.class);
    }

    /**
     * 查询单挑动态
     *
     * @param movementId 动态id
     * @return Movement
     */
    @Override
    public Movement findById(String movementId) {
        return mongoTemplate.findById(new ObjectId(movementId), Movement.class);
    }

    /**
     * 根据ids查询动态
     *
     * @param userIds ids集合
     * @return List<Movement>
     */
    @Override
    public List<Movement> findByIds(List<Long> userIds) {
        // 1. 构建查询条件  pid字段指的大数据推荐字段
        Query query = new Query();
        query.addCriteria(Criteria.where("pid").in(userIds));
        // 2. 查询执行语句
        return mongoTemplate.find(query,Movement.class);
    }

    @Override
    public PageResult findByUserId(Long uid, Integer state, Long page, Long pagesize) {
        Query query = new Query();
        if(uid != null) {
            query.addCriteria(Criteria.where("userId").is(uid));
        }
        if(state != null) {
            query.addCriteria(Criteria.where("state").is(state));
        }
        //查询总数
        long count = mongoTemplate.count(query, Movement.class);
        //设置分页参数
        query.with(Sort.by(Sort.Order.desc("created"))).limit(pagesize.intValue()).skip((page -1) * pagesize);

        List<Movement> list = mongoTemplate.find(query, Movement.class);
        return new PageResult(page,pagesize,count,list);
    }

    /**
     * 修改发布动态状态
     *
     * @param movementId
     * @param state
     */
    @Override
    public void updateById(String movementId, Integer state) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(movementId));
        Update update = new Update();
        update.set("state",state);
        mongoTemplate.updateFirst(query,update,Movement.class);
    }
}